package com.xuan.qimen.core.fei.shijia;

import com.nlf.calendar.Lunar;
import com.nlf.calendar.Solar;

import java.util.*;

/**
 * 工具
 */
public class FeiShiJiaQiMenUtil {

    /*
             《奇门遁甲断事口诀》

        十天干中甲为首，统帅其余三六九，
        三奇即是乙丙丁，分别代表曰月星。
        六仪便是戊和己，还有壬癸与庚辛，
        奇仪主要看时位，方可判断吉与凶。
        甲干隐匿六戊下，天盘地盘戊相加，
        此时谓之为伏吟，凡事闭塞静守佳。
        加乙青龙合灵门，吉兆更好凶更差；
        加丙青龙成返首，动作大利在其中，
        若逢墓迫或击刑，吉祥反而变成凶；
        加丁青龙耀光明，参拜显贵求功名，
        若值墓迫则不吉，招时惹非不得宁；
        加己贵人入牢狱，公事私事皆不利；
        加庚值符飞宫外，吉事不吉凶更凶；
        加辛青龙折了足，吉门得助事可谋，
        若逢凶门会招灾，做事有损要破财；
        加壬青龙入天牢，逢阴遇阳均无靠；
        加癸青龙交华盖，吉门吉格有福来，
        若遇凶格与凶门，谋事作为多破败。
        乙加戊则利阴害，门逢凶迫伤人财；
        加乙曰奇之伏吟，不允见贵求功名，
        安分守己莫妄动，才能无事保太平；
        加丙奇仪则顺遂，吉星进爵加官运，
        若要遇到凶煞星，夫妻双方必两分；
        加丁奇仪成相佐，百事可为文最合；
        加己曰奇则入墓，在凶门时凶必驻；
        加庚曰奇则被刑，或夫或妻有私情，
        财产之事起争端，诉讼判解难安宁；
        加辛青龙要逃遁，奴仆拐带伤六牲，
        加壬曰奇入于地，官绌是非乱尊卑；
        加癸华盖逢官星，躲灾避难匿身形。
        丙加戊为鸟跌穴，诸事谋求总洞彻；
        加乙曰月并肩行，公差私事皆可成；
        加丙月奇悖格式，文书逼迫有破失；
        加丁之际为卒奇，朱雀贵宾文书吉，
        得吉门后为天遁，常人宜处在静地；
        加己太悖入击刑，囚人遭杖文不利，
        若逢吉门则吉利，遇到凶门祸相逼；
        加庚为荧入太白，门庭破败遭资遗；
        加辛为谋事成就，有病之人无危机；
        加壬为火入天网，是非过多客不吉；
        加癸华盖悖格在，阴人害事多祸灾。
        丁加戊时龙转光，为官为民都吉祥，
        官员可遇升迁事，百姓得益可兴昌；
        加乙人遁成吉格，无论是贵还是常，
        贵人加官且进禄，常人婚喜或财旺；
        加丙星移皓月明，贵人越级得高升，
        常人虽有欢乐事，喜气之中有悲生；
        加丁星奇入太阴，文书即至喜随心；
        加己为火入勾陈，奸仇冤事因女人；
        加庚年月曰时格，文书阻隔行人归；
        加辛朱雀入牢狱，罪犯失囚官失位；
        加壬五神互相合，讼狱公平官思诏；
        加癸朱雀投江中，文书口舌两全消。
     */

    /**
     * ☆判断日期类型并返回公历日期、农历日期
     *
     * @param setting 设置
     * @return 日期
     */
    public static Map<String, Object> isDateType(FeiShiJiaQiMenSetting setting) {

        // 1、初始化日期
        Solar solar = new Solar(); // 公历日期
        Lunar lunar = new Lunar(); // 农历日期

        // 2、日期类型校验
        int dateType = setting.getDateType(); // 日期类型（0:公历。1:农历）
        if (dateType != FeiShiJiaQiMenEnum.DATE_TYPE_SOLAR.getMark() && dateType != FeiShiJiaQiMenEnum.DATE_TYPE_LUNAR.getMark()) {
            setting.setDateType(FeiShiJiaQiMenEnum.DATE_TYPE_SOLAR.getMark()); // 转为公历日期
        }

        // 3、按公历日期计算
        if (dateType == FeiShiJiaQiMenEnum.DATE_TYPE_SOLAR.getMark()) {
            // 3.1、通过公历年月日时初始化
            solar = new Solar(setting.getDate()); // 公历日期
            lunar = solar.getLunar(); // 农历日期
        }

        // 4、按农历日期计算
        if (dateType == FeiShiJiaQiMenEnum.DATE_TYPE_LUNAR.getMark()) {
            // 4.1、获取年月日时分秒
            Calendar c = Calendar.getInstance();
            c.setTime(setting.getDate());
            int year = c.get(Calendar.YEAR); // 年
            int month = c.get(Calendar.MONTH) + 1; // 月
            int day = c.get(Calendar.DATE); // 日
            int hour = c.get(Calendar.HOUR_OF_DAY); // 时
            int minute = c.get(Calendar.MINUTE); // 分
            int second = c.get(Calendar.SECOND); // 秒
            // 4.2、若设置农历月按闰月计算，则将月份设置为负数
            if (setting.getLeapMonth() == FeiShiJiaQiMenEnum.LEAP_MONTH_YES.getMark()) {
                month = -month;
            }
            // 4.3、通过农历年月日时初始化
            try {
                lunar = new Lunar(year, month, day, hour, minute, second); // 农历日期
                solar = lunar.getSolar(); // 公历日期
            } catch (IllegalArgumentException e) {
                throw new IllegalArgumentException(e.getMessage());
            }
        }

        // 5、添加公历日期、农历日期并返回
        Map<String, Object> map = new HashMap<>();
        map.put("solar", solar); // 公历日期
        map.put("lunar", lunar); // 农历日期
        return map;

    }

    /**
     * ☆判断干支设置并返回干支
     *
     * @param setting 设置
     * @param lunar   农历日期
     */
    public static Map<String, List<String>> isGanZhi(FeiShiJiaQiMenSetting setting, Lunar lunar) {

        List<String> list = new ArrayList<>();
        Map<String, List<String>> map = new HashMap<>();

        // 年干支设置（0:以正月初一作为新年的开始。1:以立春当天作为新年的开始。2:以立春交接的时刻作为新年的开始）
        int yearGanZhiSet = setting.getYearGanZhiSet();
        // 月干支设置（0:以节交接当天起算。1:以节交接时刻起算）
        int monthGanZhiSet = setting.getMonthGanZhiSet();
        // 日干支设置（0:晚子时日干支算当天。1:晚子时日干支算明天）
        int dayGanZhiSet = setting.getDayGanZhiSet();
        // 时干支设置（0:支持早子时和晚子时）
        int hourGanZhiSet = setting.getHourGanZhiSet();

        // 1、判断年干支设置
        if (yearGanZhiSet == FeiShiJiaQiMenEnum.YEAR_GAN_ZHI_CHU_YI.getMark()) {
            // 1.1、以正月初一作为新年的开始
            list.add(lunar.getYearGan()); // 年干
            list.add(lunar.getYearZhi()); // 年支
            list.add(lunar.getYearInGanZhi()); // 年干支
        } else if (yearGanZhiSet == FeiShiJiaQiMenEnum.YEAR_GAN_ZHI_LI_CHUN_DAY.getMark()) {
            // 1.2、以立春当天作为新年的开始
            list.add(lunar.getYearGanByLiChun()); // 年干
            list.add(lunar.getYearZhiByLiChun()); // 年支
            list.add(lunar.getYearInGanZhiByLiChun()); // 年干支
        } else if (yearGanZhiSet == FeiShiJiaQiMenEnum.YEAR_GAN_ZHI_LI_CHUN_SHI_KE.getMark()) {
            // 1.3、以立春交接的时刻作为新年的开始
            list.add(lunar.getYearGanExact()); // 年干
            list.add(lunar.getYearZhiExact()); // 年支
            list.add(lunar.getYearInGanZhiExact()); // 年干支
        } else {
            // 1.4、默认→ 以正月初一作为新年的开始
            list.add(lunar.getYearGan()); // 年干
            list.add(lunar.getYearZhi()); // 年支
            list.add(lunar.getYearInGanZhi()); // 年干支
        }
        map.put("yearGanZhi", list);

        // 2、判断月干支设置
        list = new ArrayList<>();
        if (monthGanZhiSet == FeiShiJiaQiMenEnum.MONTH_GAN_ZHI_DAY.getMark()) {
            // 2.1、以节交接当天起算
            list.add(lunar.getMonthGan()); // 月干
            list.add(lunar.getMonthZhi()); // 月支
            list.add(lunar.getMonthInGanZhi()); // 月干支
        } else if (monthGanZhiSet == FeiShiJiaQiMenEnum.MONTH_GAN_ZHI_SHI_KE.getMark()) {
            // 2.2、以节交接时刻起算
            list.add(lunar.getMonthGanExact()); // 月干
            list.add(lunar.getMonthZhiExact()); // 月支
            list.add(lunar.getMonthInGanZhiExact()); // 月干支
        } else {
            // 2.3、默认→ 以节交接当天起算
            list.add(lunar.getMonthGan()); // 月干
            list.add(lunar.getMonthZhi()); // 月支
            list.add(lunar.getMonthInGanZhi()); // 月干支
        }
        map.put("monthGanZhi", list);

        // 3、判断日干支设置
        list = new ArrayList<>();
        if (dayGanZhiSet == FeiShiJiaQiMenEnum.DAY_GAN_ZHI_TOMORROW.getMark()) {
            // 3.1、晚子时日干支算明天
            list.add(lunar.getDayGanExact()); // 日干
            list.add(lunar.getDayZhiExact()); // 日支
            list.add(lunar.getDayInGanZhiExact()); // 日干支
        } else if (dayGanZhiSet == FeiShiJiaQiMenEnum.DAY_GAN_ZHI_TODAY.getMark()) {
            // 3.2、晚子时日干支算当天
            list.add(lunar.getDayGanExact2()); // 日干
            list.add(lunar.getDayZhiExact2()); // 日支
            list.add(lunar.getDayInGanZhiExact2()); // 日干支
        } else {
            // 3.3、默认→ 晚子时日干支算明天
            list.add(lunar.getDayGanExact()); // 日干
            list.add(lunar.getDayZhiExact()); // 日支
            list.add(lunar.getDayInGanZhiExact()); // 日干支
        }
        map.put("dayGanZhi", list);

        // 4、判断日干支设置
        list = new ArrayList<>();
        if (hourGanZhiSet == FeiShiJiaQiMenEnum.HOUR_GAN_ZHI.getMark()) {
            // 4.1、支持早子时和晚子时
            list.add(lunar.getTimeGan()); // 时干
            list.add(lunar.getTimeZhi()); // 时支
            list.add(lunar.getTimeInGanZhi()); // 时干支
        } else {
            // 4.2、默认→ 支持早子时和晚子时
            list.add(lunar.getTimeGan()); // 时干
            list.add(lunar.getTimeZhi()); // 时支
            list.add(lunar.getTimeInGanZhi()); // 时干支
        }
        map.put("hourGanZhi", list);

        // 4、返回干支
        return map;

    }

    /**
     * 将Solar型公历日期转为String型公历日期
     *
     * @param solar 公历日期
     * @return String型公历日期（格式：yyyy年MM月dd日HH时）
     */
    public static String getSolarStr(Solar solar) {

        return solar.getYear() + "年" + solar.getMonth() + "月" + solar.getDay() + "日" + solar.getHour() + "时";
//        return solar.getYear() + "年" + solar.getMonth() + "月" + solar.getDay() + "日" + solar.getHour() + "时" + solar.getMinute() + "分" + solar.getSecond() + "秒";

    }

    /**
     * 将Lunar型农历日期转为String型农历日期
     *
     * @param lunar 农历日期
     * @return String型农历日期（格式：二〇〇〇年一月初一子时）
     */
    public static String getLunarStr(Lunar lunar) {

        // 获取小时
        int hour = lunar.getHour();

        String lunarStr;

        // 子时
        if (hour >= 23 || hour < 1) {
            // 判断早晚子时
            if (hour >= 23) {
                lunarStr = lunar + "(晚)子时";
            } else {
                lunarStr = lunar + "(早)子时";
            }
        } else {
            lunarStr = lunar + FeiShiJiaQiMenMap.HOUR_ZHI.get(hour) + "时";
        }

        return lunarStr;

    }


}
